package web;

import invertedindex.Document;
import invertedindex.Index;
import invertedindex.Search;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gson.Gson;

/**
 * Servlet implementation class SearchServlet
 */
@WebServlet("/SearchServlet")
public class SearchServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	/**
	 * Used for mapping the search result data structure to JSON.
	 */
	public class SearchResult {
		public String status = "success";
		public List<SingleResult> results;
		
		public SearchResult(NavigableMap<Double, List<Integer>> resultMap) {
			results = new ArrayList<SingleResult>();
			
			for(double rating : resultMap.keySet()) {
				for(int doc_id : resultMap.get(rating)) {
					SingleResult result = new SingleResult();
					result.doc_id = doc_id;
					result.title = "Document " + doc_id; // FIXME: pull from record
					result.rating = rating;
					results.add(result);
				}
			}
		}
	}		
	
	public class SingleResult {
		public Integer doc_id;
		public String title;
		public Double rating;
	}

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {		
		String query = request.getParameter("q");
		String debug = request.getParameter("debug");
		String document = request.getParameter("document");
		
		System.err.println("GET request with params: query = \"" + query + "\" debug = " + debug + " document = " + document);

		if(document != null) {
			System.err.println("Retrieving document");
			getDocument(document, response);
			return;
		}
		if(query != null) {
			System.err.println("Doing search");
			if(debug == null) {
				getSearchResults(query, response);
			} else {
				getFakeSearchResults(response);
			}
		} else {
			System.err.println("Returning HTML page");
			servePage("search.html", response);
		}
	}


	protected void getSearchResults(String query, HttpServletResponse response) throws IOException {
		NavigableMap<Double, List<Integer>> sorted_result;
    	response.setHeader("Content-Type", "application/json");

		PrintWriter out = response.getWriter();
    	try {
			Search mySearch = new Search(query);
	    	Map<Integer, Double> result = mySearch.compute();    	
	    	sorted_result = Search.sortedResult(result);
		} catch (Exception e) {
			System.err.println(e);
			out.println("{\"status\":\"error\"}");
			out.close();
			return;
		}

    	SearchResult result = new SearchResult(sorted_result);
    	Gson gson = new Gson();
    	out.write(gson.toJson(result));
		out.close();
	}
	
	
	private void getFakeSearchResults(HttpServletResponse response) throws IOException {
		PrintWriter out = response.getWriter();
		NavigableMap<Double, List<Integer>> resultMap = new TreeMap<Double, List<Integer>>();
		resultMap.put(0.0, new ArrayList<Integer>());
		resultMap.put(1.0, new ArrayList<Integer>());
		resultMap.put(0.5, new ArrayList<Integer>());
		resultMap.get(0.0).add(10);
		resultMap.get(1.0).add(20);
		resultMap.get(1.0).add(30);
		resultMap.get(0.5).add(40);
		SearchResult result = new SearchResult(resultMap);
		out.write(new Gson().toJson(result));
		out.close();
	}

	protected void servePage(String relativePath, HttpServletResponse response) throws IOException {
		String path = this.getServletContext().getRealPath("/WEB-INF/" + relativePath);
		response.setHeader("Content-Type", "text/html");
		
		PrintWriter out = response.getWriter();
		BufferedReader in = new BufferedReader(new FileReader(path));
        String line;
        while ( (line = in.readLine()) != null )  {
        	out.write(line);
        }
        
		out.close();
	}
	
	protected void getDocument(String docid_s, HttpServletResponse response) throws IOException {		
		int docid;
		Document doc;
		try {
			docid = Integer.parseInt(docid_s);
		} catch(NumberFormatException e) {
			response.sendError(404, "Not found");
			return;
		}
		try {
			doc = Index.retrieveDocument(docid);
		} catch(Exception e) {
			System.err.println(e);
			response.sendError(404, "Not found");
			return;
		}
		
		response.setHeader("Content-Type", "text/html");
		PrintWriter out = response.getWriter();

		out.write("<title>" + doc.title + "</title>");
		out.write(doc.text);
		out.close();
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
                "Method not allowed.");
	}

}
